package com.networknt.rpc;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;

import com.networknt.utility.StringUtils;

import io.undertow.server.HttpServerExchange;
import io.undertow.util.AttachmentKey;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public abstract class ReflectHandler implements Handler {
	public static final AttachmentKey<String> PATH = AttachmentKey.create(String.class);
	private Map<String, Method> methods = new HashMap<>();

	public ReflectHandler() {
		Method[] declaredMethods = getClass().getDeclaredMethods();
		log.info("{}", getClass().getName());
		for (Method method : declaredMethods) {
			if (Modifier.isPublic(method.getModifiers()) && ByteBuffer.class == method.getReturnType()) {
				Class<?>[] parameterTypes = method.getParameterTypes();
				if (parameterTypes.length == 2 && parameterTypes[0] == HttpServerExchange.class) {
					methods.put(method.getName(), method);
					log.info("{}", method.getName());
				}
			}
		}
	}

	@Override
	public ByteBuffer handle(HttpServerExchange exchange, Object object) {
		String path = exchange.getAttachment(PATH);
		Method method = StringUtils.isBlank(path) ? null : methods.get(path);
		if (method != null) {
			try {
				return (ByteBuffer) method.invoke(this, exchange, object);
			} catch (Exception e) {
				String msg = e.getMessage();
				if (e instanceof InvocationTargetException) {
					InvocationTargetException ex = (InvocationTargetException) e;
					Throwable t = ex.getTargetException();
					if (t != null) {
						msg = t.getMessage();
					}
				}
				log.warn("service handle failed, path: {}, ex: {}", path, msg, e);
			}
		}
		return null;
	}
}
